/**
 * Created by sun on 2015/3/12.
 */
package com.jbm.core.common;

import com.google.protobuf.GeneratedMessage;
import com.jbm.core.iface.IAcross;
import com.jbm.core.pb.PBIAcross;
import com.jbm.core.pb.PBIFileObject;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.future.WriteFuture;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.CumulativeProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolDecoderOutput;

import java.io.*;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;

public class OHDecoder extends CumulativeProtocolDecoder
{
//    private static final Logger LOGGER = Logger.getLogger(OHDecoder.class);

	private final String charset;

	public OHDecoder(String charset)
	{
		this.charset = charset;
	}

	protected boolean doDecode(IoSession session, IoBuffer in,
							   ProtocolDecoderOutput out) throws Exception
	{
		int protoc_type = Integer.parseInt((String) session.getAttribute("PROTOC_TYPE"));
		if (in.remaining() >= 1)
		{
			in.mark();// 标记当前位置，以便reset

			byte sign = in.get();
			byte pk_type = (byte) (sign & 0xf0);

			if (pk_type == 0 || pk_type == 0x10) //server 1.0 support
			{
				in.reset();
				in.mark();

				int len = 0;
				byte[] blen = new byte[4];
				in.get(blen);
				byte type = blen[0];
				type &= 0xf0;
				session.setAttribute("PROTOC_TYPE", String.valueOf(type));
				len = (int) ((blen[3] & 0xFF)
						| ((blen[2] & 0xFF) << 8)
						| ((blen[1] & 0xFF) << 16)
						| ((blen[0] & 0x0F) << 24));

				if (len > in.remaining())
				{// 如果消息内容不够，则重置，相当于不读取size
					in.reset();
					return false;// 接收新数据，以拼凑成完整数据
				} else
				{
					Object to = null;

					if (type == 0)
					{
						byte[] bbIn = new byte[len];

						in.get(bbIn, 0, len);

						ByteArrayInputStream bais = new ByteArrayInputStream(bbIn);
						ObjectInputStream ois = new ObjectInputStream(bais);
						to = ois.readObject();
						if (!to.equals("request") && !to.equals("null"))
						{
							to = new TransClass().I1_0toPB2_0(to);
							String aa = "sdg";
						}
					} else if (type == 0x10)
					{
						byte[] bslen = new byte[2];
						in.get(bslen);
						int strlen = ((bslen[1] & 0xFF)
								| ((bslen[0] & 0xFF) << 8));
						byte[] bname = new byte[strlen];
						in.get(bname, 0, strlen);
						String cname = new String(bname, "UTF8");
						String pbname = "com.jbm.jbmsupplier.pb.PB" + cname + "$" + cname;
						Object pbb = null;

						byte[] bbIn = new byte[len - strlen - 2];
						in.get(bbIn, 0, len - strlen - 2);

						try
						{
							Method nb = Class.forName(pbname).getMethod("parseFrom", byte[].class);
							pbb = nb.invoke(null, bbIn);
							to = new TransClass().PB1_0toPB2_0(to,1);
//							to = new TransClass().ProtocolBufferToI(pbb);
						} catch (Exception e)
						{
							e.printStackTrace();
						}
					}

					out.write(to);

					if (in.remaining() > 0)
					{// 如果读取内容后还粘了包，就让父类再给一次，进行下一次解析
						// System.out.println("package left="+in.remaining()+" data="+in.toString());
					}
					return true;// 这里有两种情况1：没数据了，那么就结束当前调用，有数据就再次调用
				}
			}else if ( pk_type == 0x20 )
			{
				if ( sign == 0x21 )
				{
					if (in.remaining() < 4)
					{// 如果消息内容不够，则重置，相当于不读取size
						in.reset();
						return false;// 接收新数据，以拼凑成完整数据
					}

					short index = 0;
					byte[] bidx = new byte[2];
					in.get(bidx);
					index = (short) ((bidx[1] & 0xFF)
							| ((bidx[0] & 0xFF) << 8));

					int len = 0;
					byte[] blen = new byte[2];
					in.get(blen);
					len = (int) ((blen[1] & 0xFF)
							| ((blen[0] & 0xFF) << 8));

					if (len > in.remaining())
					{// 如果消息内容不够，则重置，相当于不读取size
						in.reset();
						return false;// 接收新数据，以拼凑成完整数据
					} else
					{
						byte[] buffer = new byte[len];
						in.get(buffer);
						ConnectAgent ca = (ConnectAgent)session.getAttribute("CA_Key");

						if ( ca != null )
						{
							IAcross ia = ca.getM_excodemap().get((Integer)(int)index);

							PBIAcross.IAcross pbia = null;

							if (ia != null)
							{
								if (ia.Decode(buffer))
									pbia = (PBIAcross.IAcross) ia.getIAcross();
							} else
								return true;

							if (pbia != null)
							{
								out.write(pbia);
								ca.getM_excodemap().remove((Integer)(int)(index));
							}else
								return true;
						}

						return true;// 这里有两种情况1：没数据了，那么就结束当前调用，有数据就再次调用
					}
				}else
				{
					if (in.remaining() < 3)
					{// 如果消息内容不够，则重置，相当于不读取size
						in.reset();
						return false;// 接收新数据，以拼凑成完整数据
					}

					int len = 0;
					byte[] blen = new byte[3];
					in.get(blen);
					len = (int) ((blen[2] & 0xFF)
							| ((blen[1] & 0xFF) << 8)
							| ((blen[0] & 0xFF) << 16));

					if (len > in.remaining())
					{// 如果消息内容不够，则重置，相当于不读取size
						in.reset();
						return false;// 接收新数据，以拼凑成完整数据
					} else
					{
						byte[] pbbuffer = new byte[len];
						in.get(pbbuffer);

						PBIAcross.IAcross iacross = PBIAcross.IAcross.parseFrom(pbbuffer);

						if ((iacross.getExcode()& IAcross.excode_doexcode ) != 0 )
						{
							IAcross request = new TransClass().PB2_0toI2_0("ExCode:", iacross);

							ConnectAgent ca = (ConnectAgent)session.getAttribute("CA_Key");

							GeneratedMessage gm = (GeneratedMessage) request.StartDecode(iacross.getContent(), new IoSessionShell(session,ca,MainServer.getG_server().getM_server_type()));

							if (gm != null)
							{
								PBIAcross.IAcross.Builder iab = iacross.toBuilder();

								iab.setContent(gm.toByteString());
								iacross = iab.build();
								request.setIAcross(iacross);

								if ( ca != null )
									ca.getM_excodemap().put((Integer)(iacross.getQindex()&0x7fff),request);
							} else
							{
								PBIAcross.IAcross pbresponse = new PBRandR(iacross).BuildResponse(new IAcross(500, "附件处理错误"));

								session.write(pbresponse);
							}
						}else
							out.write(iacross);

						return true;// 这里有两种情况1：没数据了，那么就结束当前调用，有数据就再次调用
					}
				}
			}
		}

		return false;// 处理成功，让父类进行接收下个包
	}
}
